Creating a Web interface with Lua

Latest update: May 2015

With Lua, your FlashAir can dynamically generate HTML content - simply by printing HTML/JavaScript when run. It’s similar to doing web development with PHP.

In this tutorial, we’re going to over a couple basic examples.

Downloading and displaying an image

First, lets try downloading an image using fa.request and - if the download was successful - displaying it. Lets start with the FlashAir logo.

--HTTP request
result = fa.HTTPGetFile("https://flashair-developers.com/images/assets/flashairLogo_official_small.png", "logo.png")
print("<!DOCTYPE html>")
print("<html>")
print("<body><center>")
print("<h2>Hello HTML!</h2>")
if result ~= nil then
  --Display the image
  print("<img src=\"logo.png\" alt=\"FlashAir Developers Logo\">")
else
  print("File failed to download...")
end
print("</body>")
print("</html>")

That’s it! Load your script from any browser and it should work.

FlashAir status page

Next, we’re going to put together a status page. This page is going to display some useful information about the FlashAir, such as the name, SSID, the contents of a directory, etc. We’ll be collecting all this information in Lua, then printing HTML.

We’re going to load a lot of this info from SD_WLAN/CONFIG, so lets start with a loadConfig() function.

--Read the FlashAir config file, store it in a table
local function loadConfig()
	local file = io.open("/SD_WLAN/CONFIG", "r" )
	config = {}
	for line in file:lines() do
		--Split the config file into variables and values
		--ie: APPMODE=5
		var, value = line:match("([^,]+)=([^,]+)")
		if var ~= nil and value ~= nil then
			config[var] = value
		end
	end
	return config
end

Next, we’re going to make a list of the files in the directory we’re monitoring. We’re also going to do a seperate function to recursively count the total number of files there.

--Returns a list of files in a directory, as well as their size
local function getfileList(path)
	file_list = {}
	for file in lfs.dir(path) do
		attr = lfs.attributes(path.."/"..file)
		file_list[file] = attr.size
	end
	return file_list
end

--Recursively counts the number of files in a directory (not including folders)
local function countFiles(path)
	--print("Counting: "..path)
	count=0
	for file in lfs.dir(path) do
		attr = lfs.attributes(path.."/"..file)
		if attr ~= nil and attr.mode == "file" then
			count = count +1
		end
		if attr ~= nil and attr.mode == "directory" then
			count = count + countFiles(path.."/"..file)
		end
	end
	return count
end

Note that we could also get this information (or make a number of other requests) by using fa.request() to call command.cgi - but doing it with LuaFileSystem is faster.

Now that we’ve got those two functions, lets write out the rest of the script. We’ll just use basic HTML, and a refresh tag to reload the page.

reloadTime = "60" --How often (in seconds) the status page should update.
monitorDir = "/DCIM" --What directory to monitor

--load the config file
config_table=loadConfig()
file_count=countFiles(monitorDir)
file_list=getfileList(monitorDir)

print("<!DOCTYPE html>")
print("<html>")
--Set the page to reload every x seconds
print("<meta http-equiv=\"refresh\" content=\""..reloadTime.."\" />")
print("<body><center>")
if config_table["APPNAME"] ~= nil then
	print("<h2>"..config_table["APPNAME"].." Status Page</h2>")
else
	print("<h2>FlashAir Status Page</h2>")
end

if config_table["APPMODE"] ~= nil and config_table["APPSSID"] ~= nil and config_table["VERSION"]  ~= nil then
	print("<b>APPMODE:</b> "..config_table["APPMODE"].."<b>SSID:</b> <i>"..config_table["APPSSID"].."</i>")
	print("<br>")
	print("<b>Version: </b>"..config_table["VERSION"])

else
	print("<b>Error loading CONFIG file!</b>")
end
print("<br><br>")
print("<h2>"..monitorDir.."</h2>")
print("<div>")
for file,size in pairs(file_list) do
	if file ~= "" and size ~= "" then
		print("<a href="..monitorDir.."/"..file..">"..file.."</a>: "..size.."kb<br>")
	end
end
print("</div>")
print("Total files: "..file_count)
print("</body>")
print("</html>")

Note: Make sure you escape any quotes in your print statements with '\'!

All sample code on this page is licensed under BSD 2-Clause License